Responsive image attributes (sizes and srcset) in WordPress core were introduced in 4.4 version. You can read all about it here. In this article we will look into how we can improve those and also add other attributes.

Images will get those two responsive attributes (sizes and srcset) only if the image HTML is retrieved by using the function wp_get_attachment_image. Another function is also adding those if you’re using the theme header: get_header_image_tag.

But let’s focus on the wp_get_attachment_image function. There is a variable $attr that you can pass when calling it. If this variable is an array and it already has set the srcset, this function will not use the WordPress core functions to make them more responsive.

In most cases, that variable will be passed as default (an empty string) so WordPress core will add their own responsive attributes.

So how do they do it? They get the metadata information of the image (attachment) and then calculate the sizes and srcset. If you provide a $size, they get the maximum width for that image size and use that for sizes.

For the srcset it takes the image, gets all the sizes that are available from the image meta, checks where it is stored and if there are more versions of that image stored (each size). For each size that exists of that image, it will add it to srcset with the appropriate width (for thumbnail (150×150) would be image_url 150w).

Changing the responsive image attribute srcset

When srcset is created, we can control which image is the biggest that we can include. The default maximum width that will be included is 2048. But maybe we won’t need such big images at all on any page (even if we take retina or 4k into account).

So, you can change the default one by filtering max_srcset_image_width.

<?php

add_filter( 'max_srcset_image_width', 'my_function_to_change_srcset_max_width' );

/**
 * My function to have max images of 960px in width.
 * @return int
 */
my_function_to_change_srcset_max_width( $max_width ) {
  return 960;
}

Of course, WordPress will also allow you to change the whole srcset, so you can use the filter wp_calculate_image_srcset for that. This filter expects $sources to be returned. That’s an array of source arrays that have:

  • url – URL to the image,
  • descriptorx or w. We would use x for density or w for width. Depending on the value,
  • value – width (480 to get 480w) for which we want this image to show or density (2 to get 2x).

This filter also provides with additional information, so here is all you can get (in order):

  • $sources – array of sources,
  • $size_array – an array of requested width and height, first element is width, second is height,
  • $image_src – source of the image,
  • $image_meta – meta data of the image,
  • $attachment_id – image attachement ID.

So let’s say that we have 10 image sizes but we don’t want all of those there. We just want a 480 and 960.

<?php

add_filter( 'wp_calculate_image_srcset', 'my_function_to_filter_srcset' );

my_function_to_filter_srcset( $sources ) {

  $sources = array(
    480 => array(
       'url' => 'url_to_image_for_480px',
       'descriptor' => 'w',
       'value' => 480
    ),
    960 => array(
       'url' => 'url_to_image_for_960px',
       'descriptor' => 'w',
       'value' => 960
    )
  );

  return $sources;
}

What you could do here is to go over all the found sources and find the closest image to your required widths and use those.

Changing the response image attribute sizes

Attribute srcset is something that we might not need to touch. But the sizes attribute is a responsive attribute that we could tinker with a bit more.

The default value of that attribute is pretty simple. If we require, for example, a large size image which is 1024px in width, the attribute would be sizes="(max-width: 1024px) 100vw, 1024px". What does that mean? Well, it means that for views under 1024px, it will try to get the largest possible image relative to the view width and for all above 1024px, it will check for 1024px images in srcset.

What if you have a grid layout for views in width of 768px and above? And the maximum grid width is 300px, why would you want to have an image of 960px if you just need a 300px one (600px for retina)? Let’s change that!

You can do that using the filter wp_calculate_image_sizes. This filter includes several information:

  • $sizes – value of the attribute,
  • $size – requested image size or an array of width and height,
  • $image_src – url of the image,
  • $image_meta – meta of the image,
  • $attachment_id – id of the image.

So let’s now change this attribute to include several more sizes from the above scenario. Let’s imagine that we have a grid that is:

  • 1 column on 480px and below views,
  • 2 column, each 240px for views 767px and below,
  • 3 column, each 300px from views 768px and above.
<?php

add_filter( 'wp_calculate_image_sizes', 'my_function_to_change_image_sizes' );

function my_function_to_change_image_sizes( $sizes ) {
  return '(max-width: 480px) 100vw, (max-width: 767px) 240px, 300px';
}

Pretty simple, right? Let’s now see how we can change those and maybe other attributes.

Managing image attributes

When we use the above mentioned function wp_get_attachment_image, we are able to filter the attributes that will be applied on the image element.

That filter is wp_get_attachment_image_attributes and you have this information:

  • $attr – array of attributes,
  • $attachment – Attachment post object (WP_Post),
  • $size – requested size or array of width and height.

Here you can filter any possible attribute before being applied to the image element. So you could basically skip the above filters for srcset and sizes and use this filter.

Making images more responsive with custom attributes

So, for example, modern browsers enable lazy loading by default. You can add an attribute to have loading=lazy in image element.

add_filter( 'wp_get_attachment_image_attributes', 'my_function_to_add_lazy_loading' );

my_function_to_add_lazy_loading( $attr ) {
  $attr = 'lazy';
  return $attr;
}

With some techniques, sometimes the img src attribute was not set and instead we would put data-src. Then, a JavaScript library would check those and transform data-src into src so the image is loaded only when in view and the page is ready. So how would we do that?

add_filter( 'wp_get_attachment_image_attributes', 'my_function_to_change_src' );

my_function_to_change_src( $attr ) {
  $attr = $attr;
  unset( $attr );

  return $attr;
}

Be careful which responsive images you change

In the examples above, I’ve never checked the image size or any other possible argument. So the changes above would be applied to all images.

You should be careful when filtering the any attributes, even sizes or srcset. Why? Because you don’t want to change the sizes of a header image perhaps, or for some images that are not in a grid layout?

So what can we do here?

  • Check the $size if available (this could be like 'my_custom_image_size' === $size),
  • Use hooks prior those images if possible and unhook that after the images are listed
  • If you want to change only one particular image check the attachment ID if available or image meta that contains some information about it (such as the image name in the url)

Improving the WooCommerce Product Images in Loop

The “Loop” in WooCommerce is referred to the product grid that is used for displaying products in columns on your shop page.

I’ll use the default WooCommerce hooks that are used inside of each product when being listed in such loop/grid. If a theme has that changed (highly unlikely) it might not work but you can then use a different approach.

This part is available only to the members. If you want to become a member and support my work go to this link and subscribe: Become a Member

Conclusion

Responsive Images in WordPress are much easier to achieve with filters. It was easy even before with just the attributes (from 2.8.0) but with the 4.4.0 version, we got a much better way of handling sizes and srcset.

It takes some effort to set the correct image sizes for each custom page but it does pay off for you, your server and especially for your visitors and clients.

This is not a definitive guide on making WordPress images responsive since there other ways of achieving it but with this few adjustments you could get a fast result.

In a recent project (at the time of writing this), just improving the sizes attribute, we decreased the load of images by 50%. The visitors now will get the images displayed but with 50% less download size which in turn gives you a much faster site.

You can also do a lot with scripts by conditionally loading them. You can read about that in another article: Better WordPress Performance by Controlling Scripts.

Have you worked with responsive images in WordPress? What did you do to improve the responsiveness of a WordPress site?

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

One Comment

  1. This post was valuable, thank you. By using my_function_to_filter_srcset, how do you pass in the correct image URLs (‘url_to_image_for_480px’)?

    Reply

Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.